﻿using CrawlerFramework.ConfigEntity;
using CrawlerFramework.Repository;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CrawlerFramework.Models
{
    public static class ScheduledJobExtension
    {
        public static LinkConfig GetLinkConfig(this ScheduledJob job)
        {
            var configFolder = ConfigurationManager.AppSettings["XmlConfigFolder"];
            if (string.IsNullOrEmpty(configFolder))
                configFolder = Common.DefaultXmlConfigFolder;
            var path = Path.Combine(configFolder, string.Format("{0}.xml", job.LinkConfigGuid.ToString("D").ToUpper()));
            if (!File.Exists(path))
                throw new FileNotFoundException("The LinkConfig file is not exists");
            var serializer = new XmlSerializer<LinkConfig>();
            var linkConfig = serializer.Deserialize(path);

            if (job.LinkId.HasValue)
            {
                using (var linkRepo = new LinkRepository())
                {
                    var link = linkRepo.Single(l => l.LinkId == job.LinkId);
                    if (link == null)
                        return null;
                    linkConfig.Urls.Add(new Url { Context = link.Url });
                }
            }
            return linkConfig;
        }

        public static void Start(this ScheduledJob job)
        {
            job.LastStart = DateTime.Now;
            job.CrawlStatus = CrawlStatus.Processing;
        }

        public static void Finish(this ScheduledJob job, CrawlStatus crawlStatus)
        {
            job.LastEnd = DateTime.Now;
            job.CrawlStatus = crawlStatus;
            if (job.CrawlStatus == CrawlStatus.Completed)
                job.LastSuccess = DateTime.Now;
        }

        public static void Pause(this ScheduledJob job)
        {
            Finish(job, CrawlStatus.Paused);
        }

        public static bool IsRunOneTime(this ScheduledJob job)
        {
            if (job.Hours <= 0)
                return true;
            return false;
        }

        /// <summary>
        /// Get the due time parameter to input into Timer instance
        /// </summary>
        /// <param name="job"></param>
        /// <returns></returns>
        public static TimeSpan? GetDueTime(this ScheduledJob job)
        {
            // Run immediately if the job has not run anytime yet
            if (job.CrawlStatus == CrawlStatus.Initial || job.LastStart == null)
                return TimeSpan.FromSeconds(0);

            // If the job is processing then return null since we don't know  when the job will finish to schedule the timer
            if (job.CrawlStatus == CrawlStatus.Processing)
            {
                return null;
            }

            // If the job ended, calculate the remaining time to the next running
            if (job.LastEnd != null)
            {
                var lastEnd = job.LastEnd.Value;
                var timespanSinceLastRun = DateTime.Now - lastEnd;
                var diff = timespanSinceLastRun - TimeSpan.FromHours(job.Hours);

                return diff.TotalMinutes >= 0 ? diff : TimeSpan.FromHours(0);
            }

            return null;
        }
    }
}
